#include "std_c.h"
#include <stdio.h>
#include <linux/i2c-dev.h>
#include <stdlib.h>
#include "i2c.h"
#include "sht21.h"
#include "raspi.h"
#include "pcf8574.h"
#include "time.h"
#include "srf10.h"
#include <math.h>
#include <float.h>

#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

/* Defines */
#define _XOPEN_SOURCE 500
#define FILE_MODE (O_CREAT | O_WRONLY | O_APPEND)
#define BUFFER_SIZE 512

/* Global Variables */
char *input_read_buffer = NULL;
const char carriage_ret[] = "\r";
const char newline[] = "\n";
const char search_board[] = "s";
size_t input_buffer_size = 0;
int socket_fd;
int output_fd;

/* Function prototypes */
static void print_usage();
static void stream_file(const char *filename);
const char* get_value(char *buffer);
static void send_data(int iswrite, const char *tagname, const char *data, int len);
static void enter_username(char *buffer);
static void enter_password(char *buffer);
static void goto_board(char *buffer);
static void create_title(char *buffer);

/* Main */
int main(int argc, char **argv)
{
	uint32	Counter;
	int16 Temperature;
	uint8 Humidity;
	uint8 HwRev;
	int instat,instat_save;
	unsigned int srfdistance_cm, srfdistance_cm_save;
	int astat;
	int astat_save = 0;
	int E,A;
        char Mode;
	FILE	*datei;
	char text[100+1];
	time_t TimeCounter;
	time_t TimeCounterLocal;
	struct tm * Time;

	Counter = 0;
	Mode = 0;

        struct hostent *hp;
        struct sockaddr_in srv;

	char buffer[1024] = {"getstate EB1_Bit1 \n"};
	char toFHEM[100] = {0};
	char buff[1024];
	char *buff2;
	char eins[1] = {1};
	char null[1] = {0};
	int num;
	int xorbit[] = {1,2,4,8,16,32,64,128};

        /* create a connection to the server */
        srv.sin_family = AF_INET; // use the internet addr family
        srv.sin_port = htons(7072); // dedicated telnet port = 23
        srv.sin_addr.s_addr = inet_addr("127.0.0.1"); // ptt.cc IP address

        /* create the socket */
        if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
                perror("socket");
                exit(1);
        }

        /* connect to the server */
        printf("Connecting to 127.0.0.1 [FHEM localhost telnet]...\n");
        if (connect(socket_fd, (struct sockaddr*) &srv, sizeof(srv)) < 0) {
                perror("connect");
                exit(1);
        } else {
                printf("Connection succesfull.\n\n");
        }

	I2C_Open("/dev/i2c-1");  // Hardware Revision 1.0

	while (1)
	{
		time ( &TimeCounter );
		if((TimeCounter % 2) == 0)		// alle 5 sec messen
		{

			Time = localtime (&TimeCounter);   // wichtig für Timezone und Sommerzeit
			TimeCounterLocal = TimeCounter - timezone;
			if(Time->tm_isdst) TimeCounterLocal += 3600;	// Sommerzeit

			/* Eingangsbyte hex 26 einlesen */
			pcf8574_input(0x26,&instat);
			printf("\nSTATUS der Ein/Ausgaenge einlesen:\n");
			printf("Ebyte: %02x\n",instat);
			if(instat != instat_save){
				for (int i = 7; i >= 0; i--)
				{
					sprintf(toFHEM,"set EB1_Bit%d %s \n",i,((1<<i)&instat)?"on":"off");
					if ((send(socket_fd,toFHEM, strlen(toFHEM),0))== -1) {
						 fprintf(stderr, "Failure Sending Message\n");
						 close(socket_fd);
						 exit(1);
					}
					else{
					  //printf("Message being sent: %s\n",toFHEM);
					}
					DelayMs(25);
				}
			}
			instat_save = instat;

			/* Ausgangsbyte schreiben hex 0x24 */
		  pcf8574_input(0x24,&astat);
                        printf("Abyte: %02x\n",astat);
			printf("--------------------\n\n");
		  DelayMs(30);

			astat_save = 255;
			for (int i = 7; i >= 0; i--)
			{
				sprintf(toFHEM,"getstate AB1_Bit%d\n",i);
				if ((send(socket_fd,toFHEM,strlen(toFHEM),0))== -1) {
					fprintf(stderr,"Failure Sending Message\n");
					close(socket_fd);
					exit(1);
				}
				DelayMs(100);
				if ((num = recv(socket_fd, buff,1024,0))== -1) {
					fprintf(stderr,"Error in receiving message!!\n");
					perror("recv");
					exit(1);
				}
				if ( strcmp(strndup(buff+6,1),eins) ==48){
					astat_save = astat_save^xorbit[i];
				}
				else{
					astat_save = astat_save|xorbit[i];
				}
			}
			printf("Byte from FHEM to I2C: %d \n\n",astat_save);
                  	pcf8574_output(0x24,astat_save);
                        DelayMs(30);

		}

    if((TimeCounter % 20) == 0)
    {
			/* Temperatur und Luftfeuchte auslesen */
			I2C_Setup(I2C_SLAVE, 0x40); // Setze Address vom SHT21 Hex 40
			if(I2cError)
			{
				I2C_PrintError();
				exit(1);
			}
			SHT21_Read(&Temperature,&Humidity);
			printf("%.1f\t%u\n",((float)Temperature)/10,Humidity);

			sprintf(toFHEM,"set dum_Keller_Rpi_temp %.1f \n",((float)Temperature)/10);
			if ((send(socket_fd,toFHEM, strlen(toFHEM),0))== -1) {
				fprintf(stderr, "Failure Sending Message\n");
				close(socket_fd);
				exit(1);
			}
			sprintf(toFHEM,"set dum_Keller_Rpi_hum %u \n",Humidity);
			if ((send(socket_fd,toFHEM, strlen(toFHEM),0))== -1) {
				fprintf(stderr, "Failure Sending Message\n");
				close(socket_fd);
				exit(1);
			}
			DelayMs(50);

			/* SRF10 Daten einlesen */
			//srfdistance_cm = srf10daten(0x70);
//			if (srfdistance_cm != srfdistance_cm_save){
//				printf("distmain: %i \n",srfdistance_cm);
//			        sprintf(toFHEM,"set dum_SRF10_wert %i \n",srfdistance_cm);
//			        if ((send(socket_fd,toFHEM, strlen(toFHEM),0))== -1) {
//					fprintf(stderr, "Failure Sending Message\n");
//					close(socket_fd);
//					exit(1);
//				}
//		        }
//	     srfdistance_cm_save = srfdistance_cm;
    }
  sleep(1);
  }
I2C_Close();
return(0);
}

/*************************************************************/
/**             AB HIER nur noch Subs                       **/
/*************************************************************/
/**
 * print_usage:
 * Print usage information
 */ static void print_usage() {
    fprintf(stderr, "Usage: ./ptt-telnet-client [input-filename]\n");
}
/**
 * stream_file:
 * @filename: input file name to parse
 * Parse the input file and get the directives (tags)
 */ static void stream_file(const char *filename) {
        FILE *input_fp = NULL;
        /* Open input file to read directives */
        input_fp = fopen(filename, "r");
       
        /* Loop over the lines */
        while (!feof(input_fp)) {
                /* Memory allocation */
                input_buffer_size = BUFFER_SIZE * sizeof(char);
                input_read_buffer = malloc(input_buffer_size);
                if (fgets(input_read_buffer, input_buffer_size, input_fp) != NULL) {
       
                        if (strncmp(input_read_buffer, "<ID>", sizeof(char)*4)==0) {
                                enter_username(input_read_buffer); // input username in the login
                        }
                        else if (strncmp(input_read_buffer, "<PASS>", sizeof(char)*6)==0) {
                                enter_password(input_read_buffer); // input pwd in the login
                        }
                        else if (strncmp(input_read_buffer, "<BOARD>", sizeof(char)*7)==0) {
                                goto_board(input_read_buffer); // goto see the board
                        }
                        else if (strncmp(input_read_buffer, "<P>", sizeof(char)*3)==0) {
                                create_title(input_read_buffer); // create title in the board
                        }
                }
               
                free(input_read_buffer);
                input_read_buffer = NULL; // just in case; ignore double free
        }
       
        /* Done, close input file */
        fclose(input_fp);
}
/**
 * get_value:
 * @buffer: <ID> ... </ID>
 * Get the value of the corresponding node
 */ const char* get_value(char *buffer) {
        char *feedback = NULL;
        int len;
        feedback = strtok(buffer, "<>");
        feedback = strtok(NULL, "<>");
        len = strlen(feedback);
        feedback[len+1] = '\0';
        return feedback;
}
/**
 * send_data:
 * @iswrite: a boolean to check for writing into output file
 * @tagname: input tags for output file's reference
 * @data: The data which is going to be sent to the server
 * @len: Length of the data
 * Send the data to the server; it is a combination of input of data and
 * input of a carriage return
 */ static void send_data(int iswrite, const char *tagname, const char *data, int len) {
        printf("Sending data; [%s] ...\n", data);
        if (write(socket_fd, data, sizeof(char)*(len+1)) < 0) {
                perror("send_data; sending username");
                exit(1);
        }
       
        /* Input a carriage return character to complete data send */
        printf("Return.\n");
        if (write(socket_fd, carriage_ret, sizeof(char)*1) < 0) {
                perror("send_data; sending username");
                exit(1);
       
        /* Write result to the output file */
        } else {
                if (iswrite) {
                        printf("Writing tagname [%s] to output file...\n", tagname);
                        if (write(output_fd, tagname, sizeof(char)*(strlen(tagname))) < 0) {
                                perror("send_data; writing username to output file");
                                exit(1);
                        }
                        printf("Writing data; [%s] to output file...\n", data);
                        if (write(output_fd, data, sizeof(char)*(len+1)) < 0) {
                                perror("send_data; writing username to output file");
                                exit(1);
                        }
                        printf("Appending new line...\n\n");
                        if (write(output_fd, newline, sizeof(char)*1) < 0) {
                                //printf("rett: %ld\n", ret);
                                perror("send_data; appending new line in output file");
                                exit(1);
                        }
                }
        }
       
}
/**
 * enter_username:
 * @buffer: <ID> ... </ID>
 * Extract the username from ID tags and enter it in the login part
 */ static void enter_username(char *buffer) {
        const char *username;
        int username_len;
       
        username = get_value(buffer);
        username_len = strlen(username);
        printf("Extracted username: %s\n", username);
       
        /* Send the username data to the server */
        send_data(1, "ID: ", username, username_len);
        usleep(10000); // sleep for a while just in case
}
/**
 * enter_password:
 * @buffer: <PASS> ... </PASS>
 * Extract the password from tags and enter it in the login part
 */ static void enter_password(char *buffer) {
        const char *password;
        const char *invisible_pass;
        int password_len, i;
       
        password = get_value(buffer);
        password_len = strlen(password);
        printf("Extracted Password: %s\n", password);
       
        /* Send the password data to the server */
        send_data(1, "PASS: ", password, password_len);
        usleep(2000000); // sleep 2 sec to wait respond from server
       
        /* get into main page of ptt */
        //send_data(0, NULL, carriage_ret, 1);
        //usleep(10000);
        send_data(0, NULL, carriage_ret, 1);
        usleep(1000000);
        send_data(0, NULL, carriage_ret, 1);
        usleep(1000000);
}
/**
 * goto_board:
 * @buffer: <BOARD> ... </BOARD>
 * Extract the boardname from tags and goto see it
 */ static void goto_board(char *buffer) {
        const char *boardname;
        int boardname_len;
       
        boardname = get_value(buffer);
        boardname_len = strlen(boardname);
        printf("Going to [%s] board...\n", boardname);
       
        /* Send the boardname data to the server */
        send_data(0, "BOARD: ", boardname, boardname_len);
        usleep(2000000); // sleep 2 sec to wait respond from server
        send_data(0, NULL, search_board, 1);
        usleep(1000000);
        send_data(0, NULL, carriage_ret, 1);
        usleep(1000000);
}
/**
 * create_title:
 * @buffer: <P> ... </P>
 * Extract the title from tags and append it to create content of it
 */ static void create_title(char *buffer) {
        const char *title;
        int title_len;
       
        title = get_value(buffer);
        title_len = strlen(title);
        printf("Creating title [%s] in the last board...\n", title);
       
        /* Send the title data to the server */
        send_data(0, "TITLE: ", title, title_len);
        usleep(2000000); // sleep 2 sec to wait respond from server
        //send_data(0, NULL, search_board, 1);
        //usleep(1000000);
        //send_data(0, NULL, carriage_ret, 1);
        //usleep(1000000);
}
